L.AnimatedMarker = L.Marker.extend({
  options: {
    speetX: 1,
    speedList: [],
    // meters（米）
    distance: 100,
    // ms（毫秒）
    interval: 100,
    // animate on add?
    autoStart: false,
    isPlay: false,
    playCall: null,
  },

  initialize: function (latlngs, options) {
    Object.assign(this.options, options);
    this.isZooming = false;
    L.Marker.prototype.initialize.call(this, latlngs[0], options);
    this.setLine(latlngs);
    this.resetIcon();
  },

  resetIcon: function () {
    const v = this;
    var iconOption = v.options.icon.options;
    var Icon = L.DivIcon.extend({
      createIcon: function () {
        // outerDiv.style.transform is updated by Leaflet
        var outerDiv = document.createElement("div");
        outerDiv.style.width = iconOption.iconSize[0] + "px";
        outerDiv.style.height = iconOption.iconSize[1] + "px";
        outerDiv.style.position = "absolute";
        v.div = document.createElement("div");
        v.div.style.width = iconOption.iconSize[0] + "px";
        v.div.style.height = iconOption.iconSize[1] + "px";
        v.div.style.transition = "transform linear 100ms";
        v.div.style.transformOrigin = "center";
        v.div.style.transform =
          "translate3d(-" +
          iconOption.iconAnchor[0] +
          "px, -" +
          iconOption.iconAnchor[0] +
          "px, 0) rotate(" +
          v._latlngs[0].bearing +
          "deg)";
        const img = document.createElement("img");
        img.src = iconOption.iconUrl;
        img.width = iconOption.iconSize[0];
        img.height = iconOption.iconSize[1];
        v.div.appendChild(img);
        outerDiv.appendChild(v.div);
        return outerDiv;
      },
      rotate(deg) {
        if (v.before && Math.abs(v.before - deg) >= 180) {
          v.div.style.transition = "none";
        } else {
          v.div.style.transition = "transform linear 100ms";
          // var _speed = 100 / v.options.speetX + 'ms'
          // v.div.style.transition = 'transform linear ' + _speed
        }
        v.div.style.transform = `translate3d(-${iconOption.iconAnchor[0]}px, -${iconOption.iconAnchor[0]}px, 0) rotate(${deg}deg)`;
        v.before = deg;
      },
      iconSize: iconOption.iconSize,
    });
    this.icon = new Icon();
    this.setIcon(this.icon);
  },

  // Breaks the line up into tiny chunks (see options) ONLY if CSS3 animations
  // // are not supported.
  // _chunk: function (latlngs) {
  //   var i,
  //     len = latlngs.length,
  //     chunkedLatLngs = [];

  //   for (i = 1; i < len; i++) {
  //     var cur = latlngs[i - 1],
  //       next = latlngs[i],
  //       dist = cur.distanceTo(next),
  //       factor = this.options.distance / dist,
  //       dLat = factor * (next.lat - cur.lat),
  //       dLng = factor * (next.lng - cur.lng);

  //     if (dist > this.options.distance) {
  //       chunkedLatLngs.push(cur);
  //       while (dist > this.options.distance) {
  //         var bearing = cur.bearing
  //         var duration = cur.duration
  //         cur = new L.LatLng(cur.lat + dLat, cur.lng + dLng);
  //         cur.bearing = bearing
  //         cur.duration = duration
  //         dist = cur.distanceTo(next);
  //         chunkedLatLngs.push(cur);
  //       }
  //     } else {
  //       chunkedLatLngs.push(cur);
  //     }
  //   }
  //   chunkedLatLngs.push(latlngs[len - 1]);

  //   return chunkedLatLngs;
  // },

  onAdd: function (map) {
    L.Marker.prototype.onAdd.call(this, map);
    this.animate();
    this.map = map;
    const _this = this;
    map.addEventListener("zoomstart", function () {
      _this.isZooming = true;
    });
    map.addEventListener("zoomend", function () {
      _this.isZooming = false;
    });

    // Start animating when added to the map
    if (this.options.autoStart) {
      this.start();
    }
  },

  animate: function () {
    var now = Date.now();
    var end = this.startedAt + this.duration;
    if (
      now < end &&
      this.getLatLng().distanceTo(this.startLatLng) < this.nextLatLng.distanceTo(this.startLatLng)
    ) {
      if (this.isPlay) {
        requestAnimationFrame(this.animate.bind(this));
      }
    } else if (this._i < this._latlngs.length - 1) {
      if (this.speetChange) {
        this._latlngs = this._latlngsnew;
        this.speetChange = false;
      }
      this.startedAt = Date.now();
      this.startLatLng = this._latlngs[this._i];
      this.nextLatLng = this._latlngs[this._i + 1];
      this.duration = this.startLatLng.duration;
      this.setLatLng(this._latlngs[this._i]);
      this.icon.rotate(this.startLatLng.bearing);
      this._i++;
      if (this.isPlay) {
        requestAnimationFrame(this.animate.bind(this));
      }
    }

    // 解决地图缩放是图标会偏移轨迹线问题
    if (!this.isZooming && this.map) {
      var t = now - this.startedAt;
      if (t > this.duration) {
        // 解决结束时小车位置超出终点问题
        t = this.duration;
      }
      var lat =
        this.startLatLng.lat +
        ((this.nextLatLng.lat - this.startLatLng.lat) / this.startLatLng.duration) * t;
      var lng =
        this.startLatLng.lng +
        ((this.nextLatLng.lng - this.startLatLng.lng) / this.startLatLng.duration) * t;
      this.setLatLng({
        lat: lat,
        lng: lng,
      });
      // 用于动态轨迹线展示
      if (this.options.playCall) {
        this.options.playCall({
          lat: lat,
          lng: lng,
        });
      }
    }
  },

  setSpeetX: function (_speetX) {
    var speed = _speetX / this.options.speetX;
    this._latlngsnew = [];
    for (var i = 0; i < this._latlngs.length; i++) {
      var _latlng = L.latLng(this._latlngs[i].lat, this._latlngs[i].lng);
      _latlng.duration = this._latlngs[i].duration / speed;
      _latlng.bearing = this._latlngs[i].bearing;
      this._latlngsnew.push(_latlng);
    }
    this.options.speetX = _speetX;
    this.speetChange = true;
  },

  // Start the animation
  start: function () {
    this.isPlay = true;
    this.startedAt = Date.now();
    if (this.isPause) {
      this.startedAt = this.startedAt - this.playedTime;
      this.isPause = false;
    }
    this.animate();
  },

  pause: function () {
    this.playedTime = Date.now() - this.startedAt;
    this.isPause = true;
    this.isPlay = false;
  },

  // Stop the animation in place
  stop: function () {
    // console.log('stop')
    this.isPlay = false;
    this.isPause = false;
    this.startedAt = NaN;
    this._i = 0;
    this.animate();
  },

  setLine: function (latlngs) {
    // console.log('distance' + this.options.distance)
    // console.log('interval' + this.options.interval)
    for (var i = 0; i < latlngs.length; i++) {
      if (i === latlngs.length - 1) {
        latlngs[i].duration = latlngs[i - 1].duration;
        latlngs[i].bearing = latlngs[i - 1].bearing;
      } else {
        // console.log(latlngs[i]);
        if (this.options.speedList.length > 0 && this.options.speedList[i] !== undefined) {
          latlngs[i].duration =
            (latlngs[i].distanceTo(latlngs[i + 1]) / this.options.distance) *
            (this.options.interval / this.options.speedList[i]);
        } else {
          latlngs[i].duration =
            (latlngs[i].distanceTo(latlngs[i + 1]) / this.options.distance) * this.options.interval;
        }
        latlngs[i].bearing = this.getRotation(latlngs[i], latlngs[i + 1]);
      }
    }
    this._latlngs = latlngs;
    // this._latlngs = this._chunk(latlngs);
    this._i = 0;
  },

  getRotation: function (start, end) {
    // console.log(start, end);
    var dx = end.lng - start.lng;
    var dy = end.lat - start.lat;
    var radian = Math.atan2(dy, dx); //弧度值
    var rotation = (180 * radian) / Math.PI; //转换为角度值
    // if (rotation > -180 && rotation < 0) {
    //   rotation = 360 + rotation;
    // }
    // console.log(rotation);
    return 90 - rotation;
    // 将角度转换为弧度
    // var radLat1 = (start.lat * Math.PI) / 180;
    // var radLon1 = (start.lng * Math.PI) / 180;
    // var radLat2 = (end.lat * Math.PI) / 180;
    // var radLon2 = (end.lng * Math.PI) / 180;

    // var dLon = radLon2 - radLon1;

    // // 计算方位角
    // var y = Math.sin(dLon) * Math.cos(radLat2);
    // var x =
    //   Math.cos(radLat1) * Math.sin(radLat2) -
    //   Math.sin(radLat1) * Math.cos(radLat2) * Math.cos(dLon);
    // var bearing = Math.atan2(y, x);

    // // 将弧度转换为角度并规范化角度值（0-360度）
    // bearing = (bearing * 180) / Math.PI;
    // bearing = (bearing + 360) % 360;
    // console.log(bearing);
    // return bearing;
  },
});

L.animatedMarker = function (latlngs, options) {
  return new L.AnimatedMarker(latlngs, options);
};
